package com.example.netty.nio.reactor.singlethread;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * NIO 服务端 基于Reactor模型的单线程模型
 *
 * @author LSQ
 * @since 2023/2/17 19:44
 */
public class Server {

    public static void main(String[] args) {
        try {
            // 1、获取管道
            ServerSocketChannel channel = ServerSocketChannel.open();
            // 2、设置管道为非阻塞模式
            channel.configureBlocking(false);
            // 3、绑定端口
            channel.bind(new InetSocketAddress(8888));
            // 4、获取选择器
            Selector selector = Selector.open();
            // 5、将通道注册到选择器上，并且开始监听指定的接受事件
            channel.register(selector, SelectionKey.OP_ACCEPT);
            // 6、轮询已经就绪的事件
            while (selector.select() > 0) {
                System.out.println("开始事件处理...");
                // 7、获取选择器中所有注册的通道中已经准备好的事件
                Iterator<SelectionKey> it = selector.selectedKeys().iterator();
                // 8、开始遍历事件
                while (it.hasNext()) {
                    SelectionKey selectionKey = it.next();
                    System.out.println("selectionKey ---> " + selectionKey);
                    // 9、判断这个事件具体是啥
                    if (selectionKey.isAcceptable()) {
                        // 10、获取当前接入事件的客户端通道
                        SocketChannel socketChannel = channel.accept();
                        // 11、切换为非阻塞模式
                        socketChannel.configureBlocking(false);
                        // 12、将channel注册到选择器
                        socketChannel.register(selector, SelectionKey.OP_READ);
                        System.out.println("已将channel注册到selector上！");
                    } else if (selectionKey.isReadable()) {
                        // 13、获取当前选择器上的读
                        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                        // 14、读取事件
                        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                        int len;
                        while ((len = socketChannel.read(byteBuffer)) > 0) {
                            byteBuffer.flip();
                            System.out.println(new String(byteBuffer.array(), 0, len));
                            // 清除之前的数据
                            byteBuffer.clear();
                        }
                    }
                    System.out.println("");
                    // 15、处理完毕后，移除当前事件
                    it.remove();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
